import java.io.*;

import javax.bluetooth.*;
import javax.microedition.io.*;
import javax.microedition.lcdui.*;
import javax.microedition.midlet.*;

public final class BluetoothTest extends MIDlet implements CommandListener, Runnable {

	private final String SERVICE_NAME = "Bluetooth Test MIDlet";
	private final UUID SERVICE_UUID = new UUID("09876543210987654321ABCDEFFEDCBA", false);
	private final String SERVICE_URL;
	// bluetooth variables
	private LocalDevice localDevice;
	private DiscoveryAgent discoveryAgent;
	// display variables
	private final List list;
	private final Command exit, send, receive, end;
	private final Display display;
	// threading variables
	private Thread thread;
	private volatile boolean stop;

	//
	public BluetoothTest() {
		// initialize display variables
		display = Display.getDisplay(this);
		list = new List("Bluetooth Test MIDlet", List.IMPLICIT);
		exit = new Command("Exit", Command.EXIT, 1);
		send = new Command("Send", Command.OK, 2);
		receive = new Command("Start Receive", Command.ITEM, 2);
		end = new Command("Stop Receive", Command.BACK, 3);
		list.addCommand(exit);
		list.addCommand(send);
		list.addCommand(receive);
		list.setCommandListener(this);
		display.setCurrent(list);
		// initialize URL variables
		SERVICE_URL = "btspp://localhost:" + SERVICE_UUID.toString() + ";name=" + SERVICE_NAME + ";authorize=false";
	}

	protected void destroyApp(boolean arg0) throws MIDletStateChangeException {
	}

	protected void pauseApp() {
	}

	protected void startApp() throws MIDletStateChangeException {
		list.setTicker(new Ticker("Bluetooth Test MIDlet"));
		try {
			localDevice = LocalDevice.getLocalDevice();
			localDevice.setDiscoverable(DiscoveryAgent.GIAC);
			discoveryAgent = localDevice.getDiscoveryAgent();
		} catch (BluetoothStateException blue) {
			System.err.print("Error ocurred: LocalDevice; DiscoveryAgent;");
			notifyDestroyed();
		}
	}

	public void commandAction(Command c, Displayable d) {
		switch (c.getCommandType()) {
		case Command.EXIT:
			this.notifyDestroyed();
			break;
		case Command.BACK:
			list.addCommand(receive);
			list.addCommand(send);
			list.removeCommand(end);
			stop = true;
			break;
		case Command.OK:
			thread = new Thread(this);
			thread.start();
			break;
		case Command.ITEM:
			list.addCommand(end);
			list.removeCommand(send);
			list.removeCommand(receive);
			thread = new Thread(new Runnable() {
				public void run() {
					DataInputStream input;
					StreamConnection connection;
					StreamConnectionNotifier notifier = null;
					try {
						notifier = (StreamConnectionNotifier) Connector.open(SERVICE_URL);
					} catch (IOException e) {}
					while (!stop) {
						connection = null;
						try {
							connection = notifier.acceptAndOpen();
							if (connection != null) {
								input = connection.openDataInputStream();
								list.append(input.readUTF(), null);
								input.close();
								connection.close();
							}
						} catch (IOException e) { continue; }
					}
				}
			});
			thread.start();
			break;
		}
	}
	
	public void run() {
		StreamConnection connection;
		DataOutputStream output;
		try {
			connection = (StreamConnection) Connector.open(discoveryAgent.selectService(SERVICE_UUID, ServiceRecord.NOAUTHENTICATE_NOENCRYPT, false));
			output = connection.openDataOutputStream();
			output.writeUTF(SERVICE_NAME);
			output.flush();
			output.close();
		} catch (BluetoothStateException e) {
			list.append("BluetoothStateException", null);
			return;
		} catch (IOException e) {
			list.append("IOException", null);
			return;
		}
	}
}
